#pragma once

#include "Common.h"

const s32 NR_OF_KEYBOARD_KEYS = 256;

/// Keyboard key constants
const s32 KEY_ESC             = 0x01;
const s32 KEY_1               = 0x02;
const s32 KEY_2               = 0x03;
const s32 KEY_3               = 0x04;
const s32 KEY_4               = 0x05;
const s32 KEY_5               = 0x06;
const s32 KEY_6               = 0x07;
const s32 KEY_7               = 0x08;
const s32 KEY_8               = 0x09;
const s32 KEY_9               = 0x0A;
const s32 KEY_0               = 0x0B;
const s32 KEY_MINUS           = 0x0C;
const s32 KEY_EQUALS          = 0x0D;
const s32 KEY_BACKSPACE       = 0x0E;
const s32 KEY_TAB             = 0x0F;
const s32 KEY_Q               = 0x10;
const s32 KEY_W               = 0x11;
const s32 KEY_E               = 0x12;
const s32 KEY_R               = 0x13;
const s32 KEY_T               = 0x14;
const s32 KEY_Y               = 0x15;
const s32 KEY_U               = 0x16;
const s32 KEY_I               = 0x17;
const s32 KEY_O               = 0x18;
const s32 KEY_P               = 0x19;
const s32 KEY_LEFTBRACKET     = 0x1A;
const s32 KEY_RIGHTBRACKET    = 0x1B;
const s32 KEY_ENTER           = 0x1C;
const s32 KEY_LEFTCTRL        = 0x1D;
const s32 KEY_A               = 0x1E;
const s32 KEY_S               = 0x1F;
const s32 KEY_D               = 0x20;
const s32 KEY_F               = 0x21;
const s32 KEY_G               = 0x22;
const s32 KEY_H               = 0x23;
const s32 KEY_J               = 0x24;
const s32 KEY_K               = 0x25;
const s32 KEY_L               = 0x26;
const s32 KEY_SEMICOLON       = 0x27;
const s32 KEY_APOSTROPHE      = 0x28;
const s32 KEY_ACCENTGRAVE     = 0x29;
const s32 KEY_LEFTSHIFT       = 0x2A;
const s32 KEY_BACKSLASH       = 0x2B;
const s32 KEY_Z               = 0x2C;
const s32 KEY_X               = 0x2D;
const s32 KEY_C               = 0x2E;
const s32 KEY_V               = 0x2F;
const s32 KEY_B               = 0x30;
const s32 KEY_N               = 0x31;
const s32 KEY_M               = 0x32;
const s32 KEY_COMMA           = 0x33;
const s32 KEY_PERIOD          = 0x34;
const s32 KEY_SLASH           = 0x35;
const s32 KEY_RIGHTSHIFT      = 0x36;
const s32 KEY_MULTIPLY        = 0x37;
const s32 KEY_LEFTALT         = 0x38;
const s32 KEY_SPACE           = 0x39;
const s32 KEY_CAPITAL         = 0x3A;
const s32 KEY_F1              = 0x3B;
const s32 KEY_F2              = 0x3C;
const s32 KEY_F3              = 0x3D;
const s32 KEY_F4              = 0x3E;
const s32 KEY_F5              = 0x3F;
const s32 KEY_F6              = 0x40;
const s32 KEY_F7              = 0x41;
const s32 KEY_F8              = 0x42;
const s32 KEY_F9              = 0x43;
const s32 KEY_F10             = 0x44;
const s32 KEY_NUMLOCK         = 0x45;
const s32 KEY_SCROLL          = 0x46;
const s32 KEY_NUMPAD7         = 0x47;
const s32 KEY_NUMPAD8         = 0x48;
const s32 KEY_NUMPAD9         = 0x49;
const s32 KEY_SUBTRACT        = 0x4A;
const s32 KEY_NUMPAD4         = 0x4B;
const s32 KEY_NUMPAD5         = 0x4C;
const s32 KEY_NUMPAD6         = 0x4D;
const s32 KEY_ADD             = 0x4E;
const s32 KEY_NUMPAD1         = 0x4F;
const s32 KEY_NUMPAD2         = 0x50;
const s32 KEY_NUMPAD3         = 0x51;
const s32 KEY_NUMPAD0         = 0x52;
const s32 KEY_DECIMAL         = 0x53;
const s32 KEY_PIPE            = 0x56;
const s32 KEY_F11             = 0x57;
const s32 KEY_F12             = 0x58;
const s32 KEY_F13             = 0x64;
const s32 KEY_F14             = 0x65;
const s32 KEY_F15             = 0x66;
const s32 KEY_NUMPADEQUALS    = 0x8D;
const s32 KEY_PREVTRACK       = 0x90;
const s32 KEY_AT              = 0x91;
const s32 KEY_COLON           = 0x92;
const s32 KEY_UNDERLINE       = 0x93;
const s32 KEY_STOP            = 0x95;
const s32 KEY_NEXTTRACK       = 0x99;
const s32 KEY_NUMPADENTER     = 0x9C;
const s32 KEY_RIGHTCTRL       = 0x9D;
const s32 KEY_MUTE            = 0xA0;
const s32 KEY_CALCULATOR      = 0xA1;
const s32 KEY_PLAYPAUSE       = 0xA2;
const s32 KEY_MEDIASTOP       = 0xA4;
const s32 KEY_VOLUMEDOWN      = 0xAE;
const s32 KEY_VOLUMEUP        = 0xB0;
const s32 KEY_WEBHOME         = 0xB2;
const s32 KEY_NUMPADCOMMA     = 0xB3;
const s32 KEY_DIVIDE          = 0xB5;
const s32 KEY_SYSRQ           = 0xB7;
const s32 KEY_RIGHTALT        = 0xB8;
const s32 KEY_PAUSE           = 0xC5;
const s32 KEY_HOME            = 0xC7;
const s32 KEY_UP              = 0xC8;
const s32 KEY_PRIOR           = 0xC9;
const s32 KEY_LEFT            = 0xCB;
const s32 KEY_RIGHT           = 0xCD;
const s32 KEY_END             = 0xCF;
const s32 KEY_DOWN            = 0xD0;
const s32 KEY_NEXT            = 0xD1;
const s32 KEY_INSERT          = 0xD2;
const s32 KEY_DELETE          = 0xD3;
const s32 KEY_LEFTWINDOWS     = 0xDB;
const s32 KEY_RIGHTWINDOWS    = 0xDC;
const s32 KEY_APPS            = 0xDD;
const s32 KEY_POWER           = 0xDE;
const s32 KEY_SLEEP           = 0xDF;
const s32 KEY_WAKE            = 0xE3;
const s32 KEY_WEBSEARCH       = 0xE5;
const s32 KEY_WEBFAVORITES    = 0xE6;
const s32 KEY_WEBREFRESH      = 0xE7;
const s32 KEY_WEBSTOP         = 0xE8;
const s32 KEY_WEBFORWARD      = 0xE9;
const s32 KEY_WEBBACK         = 0xEA;
const s32 KEY_MYCOMPUTER      = 0xEB;
const s32 KEY_MAIL            = 0xEC;
const s32 KEY_MEDIASELECT     = 0xED;
const s32 KEY_NUMPADSTAR      = KEY_MULTIPLY;
const s32 KEY_CAPSLOCK        = KEY_CAPITAL;
const s32 KEY_NUMPADMINUS     = KEY_SUBTRACT;
const s32 KEY_NUMPADPLUS      = KEY_ADD;
const s32 KEY_NUMPADPERIOD    = KEY_DECIMAL;
const s32 KEY_NUMPADSLASH     = KEY_DIVIDE;
const s32 KEY_UPARROW         = KEY_UP;
const s32 KEY_PAGEUP          = KEY_PRIOR;
const s32 KEY_LEFTARROW       = KEY_LEFT;
const s32 KEY_RIGHTARROW      = KEY_RIGHT;
const s32 KEY_DOWNARROW       = KEY_DOWN;
const s32 KEY_PAGEDOWN        = KEY_NEXT;
const s32 KEY_CIRCUMFLEX      = KEY_PREVTRACK;

/// Keyboard key info structure
struct KeyboardKeyInfo
{
	KeyboardKeyInfo()
	{
		mValid = false;
		mLetter = false;
		mCharacter = ' ';
	}

	bool mValid;
	bool mLetter;
	c8 mCharacter;
};

/// Keyboard key state structure
struct KeyboardKeyState
{
	KeyboardKeyState()
	{
		mDelay = 0;
		mKeyDown = false;
		mKeyPressed = false;
		mKeyReleased = false;
	}

	s32 mDelay;
	bool mKeyDown;
	bool mKeyPressed;
	bool mKeyReleased;
};

class Keyboard
{
public:
	CONSTRUCTOR Keyboard();
	DESTRUCTOR ~Keyboard();

	bool Setup(HWND Window, bool Exclusive = false);
	void Shutdown();

	void Update();

	bool KeyDown(s32 Key) const;
	bool KeyPressed(s32 Key) const;
	bool KeyReleased(s32 Key) const;

	bool AnyKeyDown() const;
	bool AnyKeyPressed() const;
	bool AnyKeyReleased() const;

	void SetDelay(s32 NewDelay);
	s32 GetDelay() const;

protected:
	bool ValidKey(s32 Key) const;
	bool ValidKeyDelay(s32 KeyDelay) const;

	void AddKeyInfo(s32 Key, c8 Character, bool Letter = false);

	LPDIRECTINPUT8 DirectInput;
	LPDIRECTINPUTDEVICE8 KeyboardDevice;

	s32 Delay;
	KeyboardKeyState AnyKeyState;
	KeyboardKeyState KeyState[NR_OF_KEYBOARD_KEYS];

	KeyboardKeyInfo KeyInfo[NR_OF_KEYBOARD_KEYS];
};
